#ifndef __SYSTEM_H__
#define __SYSTEM_H__

// __asm__("movl %%esp, %%eax\n\t"	\ 
// 	"pushl $0x17\n\t"	\	ss 入栈
// 	"pushl %%eax\n\t"	\	esp 入栈
// 	"pushfl\n\t"		\	eflags 入栈
// 	"pushl $0x0f\n\t"	\ 	cs 入栈
// 	"pushl $1f\n\t"		\ 	eip 入栈
// 	"iret\n"			\ 
// 	"1:\tmovl $0x17,%%eax\n\t"	\  执行任务0,初始化段寄存器
// 	"movw %%ax, %%ds\n\t"	\ 
// 	"movw %%ax, %%es\n\t"	\ 
// 	"movw %%ax, %%fs\n\t"	\ 
// 	"movw %%ax, %%gs"	\ 
// 	:::"ax")
#define move_to_user_mode()		\
__asm__("movl %%esp, %%eax\n\t"	\
	"pushl $0x17\n\t"	\
	"pushl %%eax\n\t"	\
	"pushfl\n\t"		\
	"pushl $0x0f\n\t"	\
	"pushl $1f\n\t"		\
	"iret\n"			\
	"1:\tmovl $0x17,%%eax\n\t"	\
	"movw %%ax, %%ds\n\t"	\
	"movw %%ax, %%es\n\t"	\
	"movw %%ax, %%fs\n\t"	\
	"movw %%ax, %%gs"	\
	:::"ax")

#define printt()	\
__asm__("pushl %%eax\n\t"	\
	"pushl %%edi\n\t"		\
	"pushl $1f\n\t"		\
	"iret\n"			\
	"1:\tmovl $0xb8dd8, %%eax\n\t"	\
	"movl %%eax, %%edi\n\t"		\
	"movl $0x234, %%eax\n\t"	\
	"movl %%eax, (%%edi)\n\t"	\
	"popl %%edi\n\t"	\
	"popl %%eax\n\t"	\
	:::"ax")
	
#define move_to_cs_mode()	\
__asm__("pushl %%edx\n\t"	\
	"push %%ds\n\t"		\
	"push %%es\n\t"		\
	"push %%gs\n\t"		\
	"push %%fs\n\t"		\
	"pushl $1f\n\t"		\
	"iret\n\t"	\
	"1:\tmovl $0x10, %%edx\n\t"	\
	"mov %%dx, %%ds\n\t"	\
	"mov %%dx, %%es\n\t"	\
	"mov %%dx, %%gs\n\t"	\
	"mov %%dx, %%fs\n\t"	\
	:::"ax")

#define move_to_rep_mode()	\
__asm__("pop %%fs\n\t"	\
	"pop %%gs\n\t"		\
	"pop %%es\n\t"		\
	"pop %%ds\n\t"		\
	"popl %%edx\n\t"	\
	:::"ax")
	
#define sti()	__asm__("sti"::)
#define cli()	__asm__("cli"::)
#define nop()	__asm__("nop"::)
#define iret()	__asm__("iret"::)

// eax低4字节: 高16位0x0008代码段选择符； 低16位偏移地址
// edx高4字节: 高16位偏移地址； 低16位属性 P dpl type 等
#define _set_gate(gate_addr, type, dpl, addr) \
__asm__("movw %%dx, %%ax\n\t" \
	"movw %0, %%dx\n\t" \
	"movl %%eax, %1\n\t" \
	"movl %%edx, %2" \
	: \
	: "i"((short)(0x8000+(dpl<<13)+(type<<8))), \
	"o"(*((char*)(gate_addr))), \
	"o"(*(4+(char*)(gate_addr))), \
	"d"((char*)(addr)), \
	"a"(0x00080000))
	
// 14：interrupt, 15: trap
#define set_intr_gate(n, addr)	\
	_set_gate(&idt[n], 14, 0, addr)

#define set_trap_gate(n, addr) 	\
	_set_gate(&idt[n], 15, 0, addr)

#define set_system_gate(n, addr)	\
	_set_gate(&idt[n], 15, 3, addr)

#define _set_seg_desc(gate_addr, type, dpl, base, limit) { \
	*((gate_addr)+1) = ((base) & 0xff000000) | \
	(((base) & 0x00ff0000) >> 16) | \
	((limit) & 0xf0000) | \
	((dpl) << 13) | \
	(0x00408000) | \
	((type) << 8); \
	*((gate_addr)) = (((base) & 0x0000ffff)<< 16) | \
	((limit) & 0x0ffff); }

#define _set_tssldt_desc(n, addr, type) \
__asm__("movw $104, %1\n\t" \
	"movw %%ax, %2\n\t"		\
	"rorl $16, %%eax\n\t"	\
	"movb %%al, %3\n\t" 	\
	"movb $" type ",%4\n\t"	\
	"movb $0x00, %5\n\t"	\
	"movb %%ah, %6\n\t" 	\
	"rorl $16, %%eax"		\
	::"a"(addr), "m"(*(n)), "m"(*(n+2)), "m"(*(n+4)), \
	"m"(*(n+5)), "m"(*(n+6)), "m"(*(n+7)) \
	)

#define set_tss_desc(n, addr)	_set_tssldt_desc(((char*)(n)), addr, "0x89")
#define set_ldt_desc(n, addr)	_set_tssldt_desc(((char*)(n)), addr, "0x82")
	
#endif //__SYSTEM_H__